One of the most common development problems in embedded processor system design is the integration of firmware and hardware. A firmware development team will nearly always use some type of development aid such as a logic analyzer or a processor emulator to create working software on the system. The test instrument is used to track operation of the hardware while running the firmware. When an unexpected deviation from expected operation occurs, the instrument should provide information on the sequence of events leading up to the failure.
Two types of logic analyzers, called timing analyzers and state analyzers, are utilized to track down system failures. The timing analyzer is generally used in tracking down hardware problems, such as insufficient access time from a device or bus conflicts (e.g., a driver source driving a data bus at the wrong time). The state analyzer is used for finding incorrect firmware instruction programming of the embedded processor. A third tool, called an emulator, provides a variety of debugging techniques, but nearly always includes some form of a state analyzer to track instruction flow.
State analyzers capture the state of one or more buses during an access cycle defined by a control signal called a clock or a strobe. A "state" is simply any one of the 2.sup.n logical patterns that n-many digital signals may experience. A sequence of addresses or a sequence of fetched instructions are examples of electrical activity describable as states in a microprocessing environment and that can be monitored by a state analyzer to record their "state flow". It is assumed that at some time during the access cycle, there is valid data that is sampled by the state analyzer. This data, called a state, can be stored in sequence by a user defined set of analyzer constraints that when met, can initiate some event in the analyzer, such as initiating storage of states. For example, if the state analyzer is monitoring an address bus of an embedded processor, the analyzer could detect when the address of an invalid instruction trap occurs, and begin collecting states for storage and later examination.
To monitor the ongoing sequence of states in a system under test, a state analyzer samples the electrical values of the signals of interest at times determined by one or more clock signals associated with the system under test. The sampled electrical values obtained are compared to thresholds of selected value and polarity to determine their logical values, each of which will be either true or false, one or zero. Each resulting collection of ones and zeros for a sample is a state in the ongoing sequence of states. It is also simply a binary value that may be stored in a memory. A series of such stored values is a record of the activity occurring in the system under test. Such a record is also called a "trace".
To store an indefinitely long trace would require a corresponding indefinitely large memory. This is impractical due to both the cost of huge memories and the cost in engineering or technician time required to sort through several hundred thousand stored states, or even a few tens of thousands, to find the data that is meaningful for the problem under investigation. Some method of qualifying what states will be stored is essential to reduce the amount of trace data stored to manageable proportions while ensuring that the information in the trace is most likely to be pertinent to the investigation at hand.
Accordingly, logic state analyzers are typically equipped with sufficient memory to store traces that range from a few hundred to a few thousand states. The memories may be used as a circular buffer. That is, the newest data to be stored is written in the memory location currently containing the oldest data. The size of the trace is then limited to the memory capacity of the state memory, with the trace reflecting the most recent collected state activity occurring up to the time when the newest state was collected.
The storage of state data into the memory halts subsequent to the detection of some specified condition in the incoming state data. That condition is called the "trigger condition", or simply the "trigger". If the collection and storage of state data occurs up until a trigger condition and halts immediately upon the detection of the trigger, the trace then represents the activity that preceded the trigger. This is called a "store-before" trigger. If the collection and storage of state data were instead to begin upon detection of the trigger, the trace would then represent the activity that occurred after the trigger. This is called a "store-after" trigger. Typically, the user specifies some number of additional storage operations that is less than the memory capacity, e.g., half that number of locations. This produces a "store-about" trigger. A "store-about" trigger produces a trace that records both what states led up to the trigger, as well as those that followed it.
There are two methods of controlling the volume of states collected. The most commonly used state analyzer method is to provide the trigger capability mentioned previously (i.e., store-before, store-after, and store-about trigger capability), and with it, trigger the collection of a relatively small number of states before or after the trigger. The second method, which can be used in combination with the first, is to provide a collection match, typically referred to as a "store qualifier", which if and only if met, will cause states to be stored. Any states not meeting the store qualifier are discarded. Thus only states meeting some predefined user criteria, such as addresses within the range of an interrupt service routine, will be collected. The specification of what will cause a trigger or a collection is referred to as the analyzer's "match configuration". In all commercially available state analyzers, a single match configuration must be specified prior to the collection of the states.
One of the ways to help ensure that the trace contains principally the data that is most likely to be pertinent to the investigation at hand is to allow the trigger to represent a condition more sophisticated than simply any occurrence of a specified state. A sequential trigger, for instance, produces a trigger only when a predefined sequence of states has already occurred previous to the trigger state. The user can use a sequential trigger to define a required state flow to occur before the trigger. For example, the trigger may be desired upon fetching an instruction from the first address in a complement routine, but only if that routine is called in the context of floating point division, and not for floating point subtraction, etc. Thus, sequential triggering allows the user to specify a trigger condition that is not simply a mere place on a flow chart, but is one that has historical criteria associated with it as well.
Sequential triggering is accomplished by equipping a logic state analyzer with a mechanism to allow the user to define a sequence of states to precede a designated trigger state and a sequence detection mechanism to issue an appropriate internal trigger signal upon detection of the trigger state subsequent to the satisfaction of the sequence.
Conventional prior art state analyzers, even those having sophisticated triggering sequence capability, however, require the user to know and define the sequence of events (or states) upon which to trigger. These prior art state analyzers are inefficient when the user does not know which of a plethora of state sequences is actually causing the problem. With conventional state analyzers, a significant quantity of engineering time may be spent in a trial-an-error method of trying to correctly set up the state analyzer to capture the states that reveal the cause of the problem. A difficult firmware bug can require many retries with different configurations before the right states are captured that pinpoint the faulty firmware code. This time is also proportional to the time required in getting the bug to appear. For example, if the bug takes thirty minutes to appear, and ten state analyzer configuration set-up retries are required, five engineering hours elapse before the cause of a single firmware bug is detected. This is clearly an inefficient process, and much of the blame can be laid on the state analyzer's inability to readily capture the faulty states.